--
-- Author:      name
-- DateTime:    2018-08-21 15:57:48
-- Description: 游戏主逻辑

local skynet = require "skynet"
local log = require "Log"
local config = require "configquery"
local Timer = require "timer"
local FSM = require "fsm"
local NodeMessage = require "NodeMessage"
local Universal = require "Universal"
local json = require "cjson"
require "common"


local mix_array = mix_array
local table_clone = table_clone
local floor = math.floor
local four_five = math.four_five
local random = math.random


local MachineBase = require "common.MachineBase"
local Machine = class("Machine",MachineBase)

function Machine:ctor(tableid,rule)
	json.encode_sparse_array(true)
	self.super:ctor(tableid,rule) --父类

	--状态时间
	self.stateTime = {	
		rest = 5,		--休息时间
		wait = 3,		--等待
		start = 4,		--开始
		bank = 5,		--抢庄
		bankok = 1,		--抢庄
		bet = 5,		--开始(下注)
		leftcard = 5,	--剩余牌
		settlement = 8, --结算时间
	}
	
	--配置信息
	self.tbPlayerCard = {}
	self.tbPlayerBet = {}
	self.roomCfg = {{settlementMoneyCode = 22},--初级游戏结算
					{settlementMoneyCode = 32}, --中级游戏结算
					{settlementMoneyCode = 42}}--高级游戏结算
	local sql = string.format("select * from common_room where sub_id = %d", self.roomid)
	local res = skynet.call("mysql_service", "lua", "execute", sql)
	self.room_config = res[1]
	self.room_config.room_rule_config = json.decode(self.room_config.room_rule_config)	
	self.bottomChip = self.room_config.min_bet
	self.severFeeRate = self.room_config.room_fee/100	--服务费率
	
	--开始时系统坐庄	
	self.trdid = 0	--当前牌桌玩了几局
	self.kickDoNothingNum = 2	--玩家几局未操作踢人

	self.tbTableStateValue = {	
						start = 1,
						bank = 2,
						bank_ok = 2,
						bet = 3,
						leftcard = 4,
						settlement = 5,
						rest = 6,
						wait = 7,
					}
	--状态
	--休息，开始玩家操作，抢庄, 下注，发牌，结算
	--state1 --eventName --state2 --callback
	self.gameStateTransitionTable = {
		{"rest", 		"to_start", 			"start", 			function() self:onStart() end },
		{"rest", 		"to_wait", 				"wait", 			function() self:onWait() end },
		{"wait", 		"to_start", 			"start", 			function() self:onStart() end },
		{"start", 		"to_bank", 				"bank", 			function() self:onBank() end },
		{"bank", 		"to_bank_ok", 			"bank_ok", 			function() self:onBankOK() end },
		{"bank_ok", 	"to_bet",				"bet", 				function() self:onBet() end },
		{"bet", 	    "to_leftcard",			"leftcard", 		function() self:onLeftCard() end },
		{"leftcard", 	"to_settlement",		"settlement", 		function() self:onSettlement() end },
		{"settlement", 	"to_rest", 				"rest", 			function() self:onRest() end },
	}
	--状态机
	self.fsm = FSM.new(self.gameStateTransitionTable)
	self:reset()
end

---------------------------------------------------------
-- private
---------------------------------------------------------

--override加入玩家
function Machine:addPlayer(player)
	player.playing = player.playing or false
	player.openCard = player.openCard or false
	player.doNothingNum = player.doNothingNum or 0
	self.super.addPlayer(self, player)
end

--重置数据
function Machine:reset()
	self.rule:shuffle()
	self.tbRaceBankRate = {}
	self.tbPlayerCard = {}
	self.tbPlayerBet = {}
	self.record = {}
	self.bankData = {}
	self.operStartTime = os.time()

	for k, v in pairs(self.player_list) do
		v.openCard = false
		v.playing = false
	end
end

function Machine:removePlayer()
	for k,v in pairs(self.player_list) do 
		print("----------removePlayer ", v.chip)
		if v.disconnect or not v.ready or v.chip < self.minChip
		 or (v.doNothingNum and v.doNothingNum >= self.kickDoNothingNum)
		  then 	
		  local sql = string.format("delete from user_online where uid = %d;", k)
		  skynet.send("mysql_service", "lua", "execute", sql)
			if  v.chip < self.minChip then 
				local data = {nt_kick_table = {
					playerid = k,
					content = '金币不足请离场！',
					kick_reason = 1
				}}
				self:sendMessage(k,data)
			end			

			if v.doNothingNum and v.doNothingNum >= self.kickDoNothingNum then
				local data = {nt_kick_table = {
					playerid = k,
					content = '您已长时间未操作，将自动退出游戏。',
					kick_reason = 2,
				}}
				self:sendMessage(k,data)
			end
			--设置玩家所在桌子id为0	
			self:sendGate(v, 'update_tableid', 0)
			self:sitUp(k)
			self.player_list[k] = nil
			self:updatePlayerNum()
			print("拼十踢走掉线 or 没准备好 or 筹码不够 or 太久没有操作#######",k)
		end
	end
end

--更新大厅中传来的玩家数据
function Machine:updateProperty(playerid, data)
	local player = self.player_list[playerid]
	if not player then 
		return 
	end
	for k,v in pairs(data) do 
		player[k] = v
	end
	local seatPlayer = self:getSeatPlayer(player)      
	local data = {ps_nt_player_info_change = seatPlayer}
	self:sendToAll(data)
end

function Machine:enterTable(playerid)
	if self.player_list[playerid].seatid then
		return  
	end
	self:sitDown(playerid)
	
	if self:getState() == "wait" then
		if table.size(self.player_list) >= 2 then
			if self:getOperTime() <= 2 then				
				self:onWait()
			end
		else
			self:checkAddRobot()
		end
	end
end

--离开桌子
function Machine:leaveTable(playerid)	
	if self.player_list[playerid].playing and
	   (not (self:getState() == "rest" or  self:getState() == "wait")) then
		AssertEx(false, 'leave_table_res', 9)
	end
	log.debug('玩家离开牌桌>>>>>>>>>>>',playerid,self.tableid)
	local res = self:sitUp(playerid)
	self.player_list[playerid] = nil
	self:updatePlayerNum()
	return res
end

--掉线处理
function Machine:disconnect(playerid)	
	local player = self.player_list[playerid]
	log.debug('玩家掉线>>>>>>>>>>>',playerid,self.tableid,player.playing,player.disconnect)
	--旁观者掉线马上踢出大厅
	player.ready = false
	if not player.playing and player.disconnect then -- 在结算
		
		print("########在旁观玩家中直接踢走")	
		self:sendGate(player, 'update_tableid', 0)
		self:sitUp(playerid)
		self.player_list[playerid] = nil
		return true
	end	
	return false
end

function Machine:getPlayerInfo(playerid)
	local player = self.player_list[playerid]
	local playerInfo = {}
	if table.empty(player) then
		return {}
	end
	playerInfo.seatid = player.seatid 
	playerInfo.playerid = player.playerid 
	playerInfo.nick = player.nick 
	playerInfo.chip = player.chip 
	playerInfo.icon = player.icon 
	playerInfo.diamond = player.diamond 
	playerInfo.viplevel = player.viplevel 
	playerInfo.level = player.level
	return playerInfo
end

--
function Machine:playerRaceBank(playerid, args)
	self.player_list[playerid].doNothingNum = 0
	if self:getState() ~= "bank" then
		AssertEx(false, "ps_race_bank_res", 47)
	end
	local player = self.player_list[playerid]
	if not player.playing or self.tbRaceBankRate[player.playerid] then
		AssertEx(false, "ps_race_bank_res", 50)
	end
	self.tbRaceBankRate[playerid] = args.rate
	local data = {ps_nt_sb_bank = {tableid = self.tableid, playerid = playerid, rate = args.rate}}
	self:sendToAll(data)

	local raceBankNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if self.tbRaceBankRate[k] then
				raceBankNum = raceBankNum + 1				
			end
		end
    end
    if playingNum > 0 and raceBankNum == playingNum then
    	local callback = function ()
			self.fsm:fire("to_bank_ok")
		end
		self:setTime(1, callback)
    end
end

function Machine:checkAddRobot()
	local notRobotNum = 0
	for k,v in pairs(self.player_list) do
		if not v.robot then
			notRobotNum = notRobotNum + 1
		end
	end
	--print ("==========================>self.player_list", self.player_list)
	if notRobotNum == 0 then
		return
	end

	local playerNum = table.size(self.player_list)
	if self.maxSeatNum - playerNum >= 2 then 
		local data = {
			gameid = self.gameid,
			roomid = self.roomid,
			tableid = self.tableid,
			num = math.random(1, self.maxSeatNum - playerNum -1),
		}
		print("------------------------add robot --->", data.num, self.maxSeatNum)
		self.nodeMessage:sendGlobalService('robot_service', 'rb_nt_add', data)
	end
end

function Machine:checkRemoveRobot()
	local _removeRobot = function (player)
		if player and player.robot then
			local data = {nt_kick_table = {
			playerid = player.playerid,
			content = 'kick robot',
			}}
			self:sendMessage(player.playerid, data)
			--设置玩家所在桌子id为0	
			self:sendGate(player, 'update_tableid', 0)
			self:sitUp(player.playerid)
			self.player_list[player.playerid] = nil
			self:updatePlayerNum()
			print("kick robot---------->",player.playerid)
		end
	end

	local notRobotNum = 0
	for k,v in pairs(self.player_list) do
		if not v.robot then
			notRobotNum = notRobotNum + 1
		end
	end

	local num = table.size(self.player_list)
	if notRobotNum == 0 then --非机器人为0时踢掉
		for k,v in pairs(self.player_list) do 
			_removeRobot(v)
		end
	elseif self.maxSeatNum - num < 1 and num > notRobotNum then
		for k,v in pairs(self.player_list) do 
			if v.robot then
				_removeRobot(v)
				break
			end			
		end
	end
end
	
---------------------------------------------------------
-- 状态
---------------------------------------------------------
function Machine:onWait()
	log.debug("_______ps onWait")
	self.operStartTime = os.time()
	local callback = function ( ... )	
		if table.size(self.player_list) <= 1 then
				self:checkAddRobot()		
			return
		end			
		self.fsm:fire("to_start")		
	end
	self:setTime(self.stateTime.wait, callback)	
	self:ntWait()
end

--休息
function Machine:onRest()
	log.debug("_______ps onRest")
	self.operStartTime = os.time()

	for k,v in pairs(self.player_list) do
		if v.playing then
			v.doNothingNum = v.doNothingNum +1
		end
	end

	--重置数据
	self:reset()
	self:ntRest()
	self:removeDisconnect()	
	self:removePlayer()

--[[	for k,v in pairs(self.player_list) do
		if v.chip < self.seatMinMoney and v.seatid then
			self:sitUp(v.playerid)
		end
	end
]]--
	local callback = function ( ... )	
		if table.size(self.player_list) <= 1 then
			self.fsm:fire("to_wait")
			return
		end			
		self.fsm:fire("to_start")		
	end
	self:setTime(self.stateTime.rest, callback)
	self:checkRemoveRobot()
end


--开始
function Machine:onStart()
	log.debug("_______ps onStart")		
	self.trdid = self.trdid + 1	
	for k, v in pairs(self.player_list) do
		self.player_list[k].playing = true
	end
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(tbPlayingid) do
		self.tbPlayerCard[v] = self.rule:getCard(4)
	end	
	self:ntStart()

	--开始下注
	self.operStartTime = os.time()	
	local callback = function ()
		--停止下注
		self.fsm:fire("to_bank")
	end
	self:setTime(self.stateTime.start, callback)
	skynet.timeout(math.random(50, 200), function ()
				self:checkAddRobot()
			end)
end

function Machine:onBank()
	log.debug("_______ps onBank")
	local tbPlayingid = self:getPlayingid()
	self:ntBank()

	self.operStartTime = os.time()
	local callback = function ()
		self.fsm:fire("to_bank_ok")
	end
	self:setTime(self.stateTime.bank, callback)
end

function Machine:onBankOK()
	log.debug("_______ps onBankOk", self.tbRaceBankRate)
	
	self.bankData = {}
	local tbRatePlayer = {}	
	local maxBankRate	--最大抢庄倍数
	for playerid, rate in pairs(self.tbRaceBankRate) do
		maxBankRate = maxBankRate or rate
		if maxBankRate < rate then
			maxBankRate = rate
		end
		tbRatePlayer[rate] = tbRatePlayer[rate] or  {}
		table.insert(tbRatePlayer[rate], playerid)
	end

	local allRate = {}
	for i=1, self.maxSeatNum do
		local playerid = self.seat_list[i]
		if not playerid then
			table.insert(allRate, -1)
		else
			table.insert(allRate, self.tbRaceBankRate[playerid] or 0)
		end
	end

	local data = {}
	if maxBankRate and maxBankRate > 0 then	--有人抢庄
		if #tbRatePlayer[maxBankRate] == 1 then
			local playerid = tbRatePlayer[maxBankRate][1]
			self.bankData = {rate = maxBankRate, playerid =playerid}
			data = {ps_nt_bank_ok = {tableid = self.tableid,
									 rate = self.bankData.rate, 
									 playerid = playerid,
									 time = self.stateTime.bankok,
									 allrate = allRate }}
		elseif #tbRatePlayer[maxBankRate] > 1 then	--多人抢庄相同的倍数，随机
			local r = math.random(1, #tbRatePlayer[maxBankRate])		
			local num = table.size(tbRatePlayer[maxBankRate])	
			self.bankData = {rate = maxBankRate, playerid = tbRatePlayer[maxBankRate][r]}
			data = {ps_nt_random_bank_ok = {tableid = self.tableid, 
										    rate = self.bankData.rate, 
										    allrate = allRate, 
										    playerid = self.bankData.playerid,
										    time = self.stateTime.bankok + math.floor(num * 0.5),
										    arr_playerid = tbRatePlayer[maxBankRate]}}
		end
	else 				--没人抢庄，随机
		local tbPlayerid = self:getPlayingid()
		local r = math.random(1, #tbPlayerid)
		local num = table.size(tbPlayerid)
		self.bankData = {rate = 1, playerid = tbPlayerid[r]}
		data = {ps_nt_random_bank_ok = {tableid = self.tableid, 
										rate = self.bankData.rate, 
										allrate = allRate,
										playerid = self.bankData.playerid,
										time = self.stateTime.bankok + math.floor(num * 0.5),
										arr_playerid = tbPlayerid}}
	end

	self.operStartTime = os.time()
	local callback = function ()
		self.fsm:fire("to_bet")
	end	
	if data.ps_nt_bank_ok then
		self:setTime(self.stateTime.bankok, callback)
	else
		self:setTime(data.ps_nt_random_bank_ok.time, callback)
	end
	print("bankok data:", data)
	self:sendToAll(data)
end

function Machine:onBet()
	log.debug("_______ps onBet")
	self.operStartTime = os.time()
	self:ntBet()
	local callback = function ()
		self.fsm:fire("to_leftcard")
	end	
	self:setTime(self.stateTime.bet, callback)
end

--发剩余牌
function Machine:onLeftCard()
	log.debug("_______ps onLeftCard")	
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(tbPlayingid) do
		if v ~= self.bankData.playerid then
			self.tbPlayerBet[v] = self.tbPlayerBet[v] or self:getConfig().bet_rate[1]
		end
		table.insert(self.tbPlayerCard[v], self.rule:getCard(1)[1])
	end	
	self:ntLeftCard()
	self.operStartTime = os.time()	
	local callback = function ()
		self.fsm:fire("to_settlement")
	end
	self:setTime(self.stateTime.leftcard, callback)
end

--结算
function Machine:onSettlement()
	log.debug("_______ps onSettlement")
	
	self:beforRecord()	
	local settlementData = {}
	local tbPlayerid= self:getPlayingid()
	local bankCard = self.tbPlayerCard[self.bankData.playerid]
	local bankNiuRes = self.rule:getNiu(bankCard)
	local bankCardType = self.rule:getCardType(bankNiuRes.weight)
	local bankWinChip = 0	
	--闲家
	for k, v in pairs(self.tbPlayerBet) do
		local player = self.player_list[k]
		if player.playing and self.bankData.playerid ~= player.playerid then
		    local bet = self.bottomChip * self.bankData.rate * v 
		    local playerNiuRes = self.rule:getNiu(self.tbPlayerCard[k])
		    local playerCardType = self.rule:getCardType(playerNiuRes.weight)
		    local playerSettlement = {playerid = player.playerid, cards = playerNiuRes.card, card_type = playerCardType}
		    if bankNiuRes.weight > playerNiuRes.weight then
		    	bankWinChip = bankWinChip + bet * self.rule:getRate(bankNiuRes.weight)
		    	playerSettlement.winChips = -bet * self.rule:getRate(bankNiuRes.weight)
		    else
		    	bankWinChip = bankWinChip - bet * self.rule:getRate(playerNiuRes.weight)
		    	local severFee = math.floor(bet * self.rule:getRate(playerNiuRes.weight) * self.severFeeRate)  
		    	playerSettlement.winChips = bet * self.rule:getRate(playerNiuRes.weight) - severFee   	
		    	self.record.severFee[player.playerid] = severFee
		    end
		    table.insert(settlementData, playerSettlement) 
		end
	end

	--庄家
	local bankSettlement = {}
	bankSettlement.cards = bankNiuRes.card
	bankSettlement.card_type = bankCardType
	bankSettlement.playerid = self.bankData.playerid
	if bankWinChip > 0 then
		local severFee = math.floor(bankWinChip * self.severFeeRate)
		bankWinChip = bankWinChip - severFee
		self.record.severFee[self.bankData.playerid] = severFee
	end
	bankSettlement.winChips = bankWinChip
	table.insert(settlementData, bankSettlement)
	
	for k, v in pairs(settlementData) do
		local player = self.player_list[v.playerid]
		local reason = {
				code = self.roomCfg[self.roomid%10].settlementMoneyCode,
				moneytype = 1,
				game = player.game,
				gameid = self.gameid%10,
				gametype = self.roomid,
			}		
		--print("==========", player.playerid, v.winChips)
		local money = self:callGate(player, 'change_money', v.winChips, reason)
		print("-------------------->settlement:", self.tableid, v.playerid, money)
		if money then
			player.chip = money
		else
			log.debug("------------------>ps settlement", "winChips:", v.winChips, "player.chip:", player.chip)
		end
		v.chip = player.chip
	end
	self:sendToAll({ps_nt_end = {table_id = self.tableid, player_settle = settlementData, time = self.stateTime.settlement}})	
	self.record.settlement = settlementData	

	self.operStartTime = os.time()			
	local callback = function ()
		--休息
		self.fsm:fire("to_rest")
	end
	self:setTime(self.stateTime.settlement, callback)
	self:doRecord()
end

function Machine:beforRecord()
	self.record = {severFee = {}, settlement = {}, beforeChip = {}}
	self.record.betRate = self.tbPlayerBet
	for k, v in pairs(self.player_list) do
		if v.playing then
			table.insert(self.record.beforeChip, {playerid = v.playerid, chip = v.chip})
		end
	end
end

function Machine:doRecord()
	self.record.bottomChip = self.bottomChip
	self.record.roomid = self.roomid
	self.record.bankData = self.bankData
	local time = os.time()

	-- 服务费
	for playerid, severFee in pairs(self.record.severFee) do
		local player = self.player_list[playerid]
		local bank = 2
		if self.bankData.playerid == playerid then
			bank = 1	
		end
		local tableName = 'service_charge_log'.. os.date("%Y%m%d")
		local str = tableName .." (uid, charge, banker, sid, time, game, gameid, gametype)"
		local sql = string.format("insert into %s values(%d,%d,%d,%d,%d,%d,%d,%d);",
			str, playerid, severFee, bank, player.seatid or 0, time, player.game or 0, self.gameid%10, self.roomid)
		local r = skynet.send("mysql_log", "lua", "execute", sql)
	end

	local tableName = 'qclandlord_tablelog'
	
	local str = tableName .." (tid, trdid, svid, tlcnt, tllog, tltime, game, gametype)"
	local sql = string.format("insert into %s values(%d,%d,%d,%d,'%s',%d,%d,%d);",
		str, self.tableid, self.trdid, 10, table.size(self.player_list), json.encode(self.record), time, self.gameid%10, self.roomid)
	local res = skynet.call("mysql_log", "lua", "execute", sql)

	local tlid = res.insert_id
	for k, v in pairs(self.record.settlement) do
		local wlfold
		if v.playerid == self.bankData.playerid then
			wlfold = self.bankData.rate
		else
			wlfold = self.tbPlayerBet[v.playerid]
		end		
		local player = self.player_list[v.playerid]
		local wlleft = player.chip
		local wlwin = v.winChips
		local wlflag
		if wlwin > 0 then wlflag = 1 else wlflag = 0 end		

		local str1 = 'qclandlord_winlog' .. " (tlid, uid, pfid, usid, tid, room_id, svid, trdid, wlfold, wlleft, wlwin, wlflag, wltime, game, gameid, gametype)"
		local sql1 = string.format("insert into %s values(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d);", str1, tlid, v.playerid, player.pfid or 0, player.usid or 0,self.tableid, self.roomid, 9,
														self.trdid, wlfold, wlleft, wlwin, wlflag, time, player.game or 0,self.gameid%10, self.roomid)
		local res = skynet.call("mysql_log", "lua", "execute", sql1)
		--print("-------------------------------->res sql1",res, sql1)
	end


end

--取桌子状态
function Machine:getTableStatus(playerid)
	local seatPlayers = self:getSeatPlayers()
	for k, v in pairs(seatPlayers) do
		local player = self.player_list[v.playerid]
		v.open_card = player.openCard

		if self:getState() == "leftcard" and v.openCard 
		   or self:getState() == "settlement"
		   or playerid == v.playerid then

			v.cards = self.tbPlayerCard[v.playerid]
			if self:getState() == "settlement" and v.playing then
				v.open_card = true
				local cards = self.tbPlayerCard[v.playerid]
				local weight = self.rule:getNiu(self.tbPlayerCard[player.playerid]).weight
				v.card_type = self.rule:getCardType(weight)
			end
		end
		if v.playing then
			if self:getState() == "bank" then
				v.max_bank_rate = self:getRaceBankRate(v.chip)
			end

			if self:getState() == "bet" and 
				self.bankData.playerid and self.bankData.playerid ~= v.playerid then
				v.max_bet_rate = self:getPlayerRate(v.chip)
			end

			if self.bankData.playerid and self.bankData.playerid ~= v.playerid then
				v.already_bet_rate = self.tbPlayerBet[v.playerid]
			end
			v.already_bank_rate = self.tbRaceBankRate[v.playerid]
		end
	end
	local status = {		
		tableid = self.tableid,
		seat_player = seatPlayers,
		config = self:getConfig(),
		time = self:getOperTime(), --当前操作所剩余时间
		state = self.tbTableStateValue[self:getState()],
		playing = self.player_list[playerid].playing,
		bankerPlayerid = self.bankData.playerid,
	}	

	--log.debug("playerid:" ..playerid, "pinshi Table status ################",status)	
	return status
end

--请求下注
function Machine:onPlayerBet(playerid, args)
	local player = self.player_list[playerid]
	player.doNothingNum = 0
	if self:getState() ~= "bet" then
		AssertEx(false, "ps_bet_res", 32)
	end
	if args.rate > self:getMaxPlayerRate() then
		AssertEx(false, "ps_bet_res", 48)
	end
	
	if not player.playing or self.tbPlayerBet[player.playerid] then
		AssertEx(false, "ps_bet_res", 49)
	end
	
	if self.bankData.playerid == playerid then
		AssertEx(false, "ps_bet_res", 36)
	end

	if self.tbPlayerBet[playerid] then --已经下注
		return
	end	
	self.tbPlayerBet[playerid] = args.rate

	local data = {ps_nt_sb_bet = {tableid = self.tableid, 
								  playerid = playerid,
								  seatid = player.seatid,
								  rate = args.rate
								  }}
    self:sendToAll(data)

    local betNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if self.tbPlayerBet[k] then
				betNum = betNum + 1				
			end
		end
    end
    if playingNum > 0 and betNum == playingNum - 1 then --全部下注了提前发剩余牌
    	local callback = function ()
			self.fsm:fire("to_leftcard")
		end
		self:setTime(1, callback)
    end

	return {}
end

--请求亮牌
function Machine:onOpenCard(playerid, args)
	if self:getState() ~= "leftcard" or self.player_list[playerid].openCard then
		return
	end
	self.player_list[playerid].openCard = true
	self.player_list[playerid].doNothingNum = 0
	local playerNiuRes = self.rule:getNiu(self.tbPlayerCard[playerid])
	local playerCardType = self.rule:getCardType(playerNiuRes.weight)	
	local data = {ps_nt_sb_open_card = {tableid = self.tableid, 
										playerid = playerid, 
										seatid =self.player_list[playerid].seatid,
										cards = playerNiuRes.card,
										card_type = playerCardType,
										}}
    self:sendToAll(data)

    local openCardPlayingNum = 0 
    local playingNum = 0
    for k,v in pairs(self.player_list) do
    	if v.playing then
    		playingNum = playingNum + 1
			if v.openCard then
				openCardPlayingNum = openCardPlayingNum + 1				
			end
		end
    end
    if playingNum > 0 and openCardPlayingNum == playingNum then
    	local callback = function ()
			self.fsm:fire("to_settlement")
		end
		self:setTime(1, callback)
    end
	return {}
end

--@override
function Machine:sitDownCallback(playerid)
	print("------------------------------------>sitDownCallback", playerid)
	local player = self:getPlayerInfo(playerid)
	local data = {ps_nt_seat_change = {
		tableid = self.tableid,
		seat_player = player,
		seat = true,
	}}	
	self:sendToOther(playerid, data)
end


--@override
function Machine:sitUpCallback(seatid, playerid)
	local player = self:getPlayerInfo(playerid)
	local data = {ps_nt_seat_change = {
		tableid = self.tableid,
		seat_player = player,
		seat = false,
	}}	
	self:sendToOther(playerid, data)
end

-------------------------------------------------------------------------------
-- 推送消息
-------------------------------------------------------------------------------
function Machine:ntStart()
	local tbPlayerid = {}
	for k, v in pairs(self.player_list) do
		local data = {ps_nt_start={
 		tableid = self.tableid,	
 		time = self.stateTime.start, 
 		cards = self.tbPlayerCard[k],		
 		playingid_list = self:getPlayingid(), 		
		}}
		
		self:sendMessage(k, data)
	end
	
	log.debug("__________ps_ntStart", data)
end

function Machine:ntWait()
	local data = {ps_nt_wait={
 		tableid = self.tableid,	
	}}
	self:sendToAll(data)
end

function Machine:ntBank()
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(self.player_list) do
		local rate = nil
		if v.playing then
			rate = self:getRaceBankRate(v.chip)			
		end
		local data = {ps_nt_bank = {
					time = self.stateTime.bank,
					max_bank_rate = rate,
					}}
		self:sendMessage(k, data)
	end	
end

function Machine:ntBet()	
	for k, v in pairs(self.player_list) do	
		local rate = nil
		if v.playing then
			rate = self:getPlayerRate(v.chip)	
		end
		
		local data = {ps_nt_bet = {
					time = self.stateTime.bet,
					max_bet_rate = rate,
					}}
		self:sendMessage(k, data)
	end	
end

function Machine:ntRest()
	self:reset()
	local data = {ps_nt_rest={
 		tableid = self.tableid,	
 		time = self.stateTime.rest
	}}
	print("_________ps_ntRest", data)
	self:sendToAll(data)	
end

function Machine:ntLeftCard()
	local tbPlayingid = self:getPlayingid()
	for k, v in pairs(self.player_list) do	
		local cards = {}
		if v.playing then
			cards = {self.tbPlayerCard[k][#self.tbPlayerCard[k]]}
		end
		local data = {ps_nt_left_card = {
					time = self.stateTime.leftcard,
					cards = cards
					}}
		self:sendMessage(k, data)
	end	
end

-----------------------------------------------------------------------------------
----------------------------------
-- 数据操作
----------------------------------

--状态对应的数字
function Machine:getStateNum()
	local state = self:getState()
	for k, v in pairs(self.gameStateTransitionTable) do 
		if state == v[1] then 
			return k
		end
	end
	return 
end

--桌子相关配置
function Machine:getConfig()
	local bank_rate = self.room_config.room_rule_config["bankrate"]
	local bet_rate = self.room_config.room_rule_config["betrate"]
	return {time_rest = self.stateTime.rest,
			time_start = self.stateTime.start,
			time_card = self.stateTime.card,
			time_end = self.stateTime.settlement,
			bank_rate = bank_rate,
			bet_rate = bet_rate,
			room_type = self.roomid%10,
			bottom_chip = self.bottomChip,
	}
end

--正在玩的
function Machine:getPlayingid()
	local tbPlayerid = {}
	for k, v in pairs(self.player_list) do
		if v.playing then
			table.insert(tbPlayerid, v.playerid)
		end
	end
	return tbPlayerid
end

--抢庄赔率
function Machine:getRaceBankRate(chip)
	local rate = chip/(self.bottomChip * (#self:getPlayingid() - 1) * self:getMaxPlayerRate() * self:getMaxCardRate())
	return math.floor(rate) 
end

--闲家下注赔率
function Machine:getPlayerRate(chip)
	local bankPlayer = self.player_list[self.bankData.playerid]
	local rate =  chip /(self.bottomChip *(#self:getPlayingid() - 1) * self:getMaxCardRate() * self.bankData.rate)
	return math.floor(rate) 
end

--闲家下注最高倍数
function Machine:getMaxPlayerRate()
	local bet_rate  = self:getConfig().bet_rate
	return bet_rate[#bet_rate]
end

--牌型最高赔率
function Machine:getMaxCardRate()
	return self.rule:getRate(self.rule.tbWeight.wxn)
end

--给所有在线玩家发消息
function Machine:sendToAll(data)
	local playerList = {}	
	for k,v in pairs(self.player_list) do 
		if not v.disconnect and v.ready  then 
			table.insert(playerList,k)
		end
	end
	if next(playerList) then
		self.nodeMessage:broadcastAllGate(playerList, data)
	end
end

----------------------------------------------------------------------------------------------
---------开始游戏
---------------------------------------------------------------------------------------------- 
function Machine:start()
	self.fsm:set("rest")
	self.fsm:fire("to_wait")
end

return Machine